/**
 * Partial 实现
 * 1.通过 keyof 拿到 T 所有属性名
 * 2.通过 in 便利属性名并赋值给 P
 * 3.通过T[P]取得相应的属性值与类型
 * 4.中间使用?,用于把属性变为可选
 */
type myPartial<T> = {
    [P in keyof T]?: T[P]
}

// 举例说明
interface UserInfo {
    id: string;
    name: string
}
/**
 * 如果不使用 Partial，则必须属性名、属性个数，属性类型符合缺一不可
 */
/* const mike: UserInfo = {
    id: '1'
} */

type NewUserInfo = Partial<UserInfo>
// 使用 Partial 后
/* type NewUserInfo = {
    id?: string | undefined;
    name?: string | undefined;
} */
const tom: NewUserInfo = {
    name: 'tom'
}

// DeepPartial
interface userInfoDeep {
    name: string,
    count: {
        math: number,
        english: number 
    }
}
type NewUserInfoDeep = Partial<userInfoDeep>
/* const mike: NewUserInfoDeep = {
    count: {
        chinese: 100
    }
} */

type DeepPartial<T> = {
    // 如果是 object， 则递归类型
    [U in keyof T] ?: T[U] extends object
        ? DeepPartial<T[U]>
        : T[U]
} 

type NewUserInfoDeepPar = DeepPartial<userInfoDeep>
/* type NewUserInfoDeepPar = {
    name?: string | undefined;
    count?: DeepPartial<{
        math: number;
        english: number;
    }> | undefined;
} */
const mike: NewUserInfoDeepPar = {
    count: {
        math: 10
    }
}